Post

Replies

Boosts

Views

Activity

Reply to Shadows: Using a shadow map
After over a week of wandering around in the dark, I discovered how convert the coordinates. The input shadowSpacePosition is in Metal Normalized Coordinates: x and y -1 to 1, z 0 to 1 with the origin at the center of the drawable. When this is stored in the depth texture it is converted to texture coordinates: x,y and z 0 to 1 with the origin on the bottom-left. So to read the proper depth in the depth texture the code is: &#9;&#9; constexpr sampler shadowSampler(coord::normalized, &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; filter::linear, &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; address::clamp_to_zero, &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; compare_func:: less); &#9;&#9;shadowPosition = in.shadowSpacePosition.xyz; &#9;&#9;shadowPosition.y *= -1; &#9;&#9;shadowPosition.xy += 1.0; &#9;&#9;shadowPosition.xy /= 2; &#9;&#9;cmp = shadowTexture.sample_compare(shadowSampler, shadowPosition.xy , shadowPosition.z); &#9; if(cmp < 0.1) &#9;&#9;&#9; isShadow = true; &#9;&#9;else &#9;&#9;&#9;&#9;isShadow = false;
Dec ’20
Reply to NSKeyedArchiver
I copied the pruneTableP2 into an NSData object and now unarchivedObjectOfClass: will read in the archive. It doesn't like NSMutableData. But now it throws out a couple of warnings. 2021-11-03 22:31:46.749411-0500 Cube Console[8846:238300] [general] *** -[NSKeyedUnarchiver validateAllowedClass:forKey:] allowed unarchiving safe plist type ''NSData' (0x1ed406558) [/System/Library/Frameworks/CoreFoundation.framework]' for key 'NS.objects', even though it was not explicitly included in the client allowed classes set: '{( "'NSDictionary' (0x1ed4065d0) [/System/Library/Frameworks/CoreFoundation.framework]" )}'. This will be disallowed in the future. 2021-11-03 22:31:46.749801-0500 Cube Console[8846:238300] [general] *** -[NSKeyedUnarchiver validateAllowedClass:forKey:] allowed unarchiving safe plist type ''NSString' (0x1ed434848) [/System/Library/Frameworks/Foundation.framework]' for key 'NS.keys', even though it was not explicitly included in the client allowed classes set: '{( "'NSDictionary' (0x1ed4065d0) [/System/Library/Frameworks/CoreFoundation.framework]" )}'. This will be disallowed in the future.
Nov ’21
Reply to NSKeyedArchiver
pruneTableP2 is an NSData object holding a 200+mbyte table. The first time the user launches the program the table must be calculated and that routine uses an NSMutableData object for that. This is archived to the users home directory to be loaded from disk thereafter. So, although typed as NSData, pruneTableP2 actually is a pointer to an NSMutableData object when it is archived. Sometime after the app was written stricter type checking was added to NSKeyedUnarchiver and the code broke. The fix is to use a pure NSData object rather than its subclass to create the archive. It is disturbing that even then the runtime sends out these warnings: Multiline 2021-11-04 08:24:55.954653-0500 Cube Console[1366:19975] [general] *** -[NSKeyedUnarchiver validateAllowedClass:forKey:] allowed unarchiving safe plist type ''NSData' (0x1dda3e558) [/System/Library/Frameworks/CoreFoundation.framework]' for key 'NS.objects', even though it was not explicitly included in the client allowed classes set: '{( "'NSDictionary' (0x1dda3e5d0) [/System/Library/Frameworks/CoreFoundation.framework]" )}'. This will be disallowed in the future . 2021-11-04 08:24:55.955503-0500 Cube Console[1366:19975] [general] *** -[NSKeyedUnarchiver validateAllowedClass:forKey:] allowed unarchiving safe plist type ''NSString' (0x1dda6c848) [/System/Library/Frameworks/Foundation.framework]' for key 'NS.keys', even though it was not explicitly included in the client allowed classes set: '{( "'NSDictionary' (0x1dda3e5d0) [/System/Library/Frameworks/CoreFoundation.framework]" )}'. This will be disallowed in the future. BlockQuote code-block
Nov ’21
Reply to Random Numbers
I found the docs I needed: [https://developer.apple.com/documentation/security/1399291-secrandomcopybytes?language=objc). The core foundation security services api contains the appropriate system call. The modern implementation of the above would be: -(uint64)random64 { uint64_t value = 0; uint8 randomByte; int i, err; for (i = 0 ; i < sizeof(value); i++) { value <<= 8; err = SecRandomCopyBytes( kSecRandomDefault , 1 , &randomByte ); value |= randomByte; } return value; }
Nov ’21
Reply to NSKeyedArchiver
Using the more explicit method: unarchivedDictionaryWithKeysOfClasses:objectsOfClasses:fromData:error: eliminates all the problems. The following code executes with no errors. -(void)test: (NSString *)input { NSDictionary *source, *destination; NSSet *classes; NSMutableData *mData1, *mData2; NSData *table1, *table2, *archive; NSError *error; @autoreleasepool { mData1 = [NSMutableData dataWithData: edgeTableC3v]; mData2 = [NSMutableData dataWithData: cornerTableC3v]; table1 = mData1; table2 = mData2; source = [NSDictionary dictionaryWithObjectsAndKeys: input, @"input", table1, @"edge table", table2, @"corner table", nil]; archive = [NSKeyedArchiver archivedDataWithRootObject: source requiringSecureCoding: YES error: &error]; if( error != nil ) { [self report: [NSString stringWithFormat: @"\nError creating archive\n\t%@", [error localizedFailureReason]]]; } else { classes = [NSSet setWithObjects: [NSData class], [NSString class], nil]; destination = [NSKeyedUnarchiver unarchivedDictionaryWithKeysOfClasses: [NSSet setWithObject: [NSString class]] objectsOfClasses: classes fromData: archive error: &error]; if( error != nil) { [self report: [NSString stringWithFormat: @"\nError reading archive\n\t%@", [error localizedFailureReason]]]; } else [self report: [NSString stringWithFormat: @"\nNo Error\n%@", [destination description]]]; } [self reportDone]; } } OUTPUT No Error { "corner table" = {length = 2449440, bytes = 0x88a40000 e0970000 98c40000 48b70000 ... f3b00000 85a40000 }; "edge table" = {length = 145152, bytes = 0x00000000 00000000 140b0000 250a0000 ... 99090000 bf080000 }; input = Parameters; } Note that I archived NSMutableData objects and they were unarchived with no error. The runtime doesn't send any warnings when unarchiving.
Nov ’21
Reply to GCD dispatch_apply()
I think I have a clearer picture of what the problem is. The code block is an IDA (Iterative Deepening Algorithm) search in the Cayley graph of the Rubik's Cube group for a solution to a cube position. For the first few iterations the code block returns almost immediately. As the search goes deeper the times increase exponentially. The problem is that GCD profiles the block based on the early iterations and decides it would be more efficiently run serially. So, when the search reaches a deeper level where parallel processing gives a huge performance increase GCD continues to run the tasks one at a time. How can one preempt that profiling?
Dec ’21
Reply to GCD dispatch_apply()
Rather than have dispatch_apply() run the loop I have replaced the above with repeated calls to dispatch_async() to avoid the problem. The following code works like a hose. - (void)searchTreeBranches { int n; RBK_Turn turn; // load up the processor cores for ( n = 0 ; n < turnsMax; n++) { turn = turns[n]; dispatch_async( myDispatchQueue, ^( void ) { ••• }); } }
Dec ’21
Reply to Left Hand Coordinates???
Included in the sample code project MigratingOpenGLCodeToMetal is the file AAPLMathUtilities. This file contains two functions for creating projection matrixes: /// Constructs a symmetric perspective Projection Matrix /// from left-handed Eye Coordinates to left-handed Clip Coordinates, /// with a vertical viewing angle of fovyRadians, the specified aspect ratio, /// and the provided absolute near and far Z distances from the eye. matrix_float4x4 AAPL_SIMD_OVERLOAD matrix_perspective_left_hand(float fovyRadians, float aspect, float nearZ, float farZ); /// Constructs a symmetric perspective Projection Matrix /// from right-handed Eye Coordinates to left-handed Clip Coordinates, /// with a vertical viewing angle of fovyRadians, the specified aspect ratio, /// and the provided absolute near and far Z distances from the eye. matrix_float4x4 AAPL_SIMD_OVERLOAD matrix_perspective_right_hand(float fovyRadians, float aspect, float nearZ, float farZ); So, I guess one can define the geometry of one's objects using either a right hand or a left hand coordinate system and have it display properly depending on which of these two one uses to construct the projection matrix. This is good. I think I understand things much better now.
Dec ’21
Reply to NSButton Failing to Reflect a Change of its Image
I found a work around to the problem. In the example code below, in response to a color change the action message, newColor:, changes the color of the image and calls the button's setImage: message. This actually is the same NSImage object already in the Button. In this case the API ignores the setNeedsDisplay message. If a new NSImage object is created, as in the line commented out, and sent to the Button, the Button is redrawn with the new image. I still think it is a bug that the in the first instance the setNeedsDisplay message is ignored. // AppDelegate.m // TestUI // // Created by Bruce D MacKenzie on 11/20/22. // #import "AppDelegate.h" @interface AppDelegate () { } @property (strong) IBOutlet NSWindow *window; @property (assign) IBOutlet NSButton *theButton; @end @implementation AppDelegate { NSImage *image; } @synthesize theButton; - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { // Insert code here to initialize your application } - (void)applicationWillTerminate:(NSNotification *)aNotification { // Insert code here to tear down your application } -(void)awakeFromNib { image = [[NSImage alloc] initWithSize: NSMakeSize( 32 , 32 )]; [image lockFocus]; [[NSColor redColor] drawSwatchInRect: NSMakeRect(0, 0, 32, 32)]; [image unlockFocus]; [[self theButton] setImage: image]; } - (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app { return YES; } -(IBAction)newColor: (NSColorWell *)sender { NSColor *newColor; newColor = [sender color]; // image = [[NSImage alloc] initWithSize: NSMakeSize( 32 , 32 )]; [image lockFocus]; [newColor drawSwatchInRect: NSMakeRect( 0, 0, 32, 32)]; [image unlockFocus]; [[self theButton] setImage: image]; [[self theButton] setNeedsDisplay: YES]; } code-block
Nov ’22
Reply to How can I pad an NSImage with white pixels in Objective-C?
If what you need to do is add a white border around and image, here's some code -(NSImage *)addBorderToImage: (NSImage *)oldImage width: (CGFloat)w; { NSSize size; NSRect iRect; NSImage *newImage; size = oldImage.size; iRect.origin.x = w; iRect.origin.y = w; iRect.size = size; size.width += 2 * w; size.height += 2 * w; newImage = [[NSImage alloc] initWithSize: size]; [newImage lockFocus]; [[NSColor whiteColor] drawSwatchInRect: NSMakeRect( 0 , 0 , size.width, size.height)]; [oldImage drawInRect: iRect]; [newImage unlockFocus]; return newImage; } code-block
Nov ’22